package src.work.ParkingManagement;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.awt.*;
import java.io.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Random;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class ParkingSystemSwing {
        public static void main(String[] args) {
                ParkingFrame frame = new ParkingFrame();
                frame.setVisible(true);
        }
}
class ParkingFrame extends JFrame {
        private final ParkingLot parkingLot = new ParkingLot(20);
        private final AtomicInteger totalIncome = new AtomicInteger(0);
        private final AtomicInteger vehicleCount = new AtomicInteger(0);
        private final BlockingQueue<String> logQueue = new LinkedBlockingQueue<>();
        private volatile boolean isPaused = false;
        private final ReentrantLock pauseLock = new ReentrantLock();
        private final Condition pauseCondition = pauseLock.newCondition();
        // GUI组件
        private JLabel lblSpaces;
        private JProgressBar progressBar;
        private JTextArea logArea;
        private JList<String> vipList;
        private DefaultListModel<String> vipListModel;
        private JLabel lblIncome;
        private JLabel lblCount;
        public ParkingFrame() {
                initUI();
                startThreads();
                startLogWriter();
        }
        private void initUI() {
                setTitle("停车场管理系统");
                setSize(600, 400);
                setDefaultCloseOperation(EXIT_ON_CLOSE);
                // 主面板布局
                JPanel mainPanel = new JPanel(new BorderLayout(10, 10));
                mainPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
                //菜单栏
                JMenuBar menuBar = new JMenuBar();
                JMenu menu = new JMenu("文件");
                JMenuItem saveItem = new JMenuItem("保存");
                JMenuItem openItem = new JMenuItem("打开");
                saveItem.addActionListener(e -> {
                        JFileChooser fileChooser = new JFileChooser();
                        FileNameExtensionFilter filter = new FileNameExtensionFilter("Text Files", "txt");
                        fileChooser.setFileFilter(filter);
                        int returnVal = fileChooser.showSaveDialog(this);
                        if (returnVal == JFileChooser.APPROVE_OPTION) {
                                File file = fileChooser.getSelectedFile();
                                try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
                                        writer.write(logArea.getText());
                                }
                                catch (IOException ex) {
                                        JOptionPane.showMessageDialog(this, "无法保存文件: " + ex.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
                                }
                        }
                });
                openItem.addActionListener(e -> {
                        JFileChooser fileChooser = new JFileChooser();
                        FileNameExtensionFilter filter = new FileNameExtensionFilter("Text Files", "txt");
                        fileChooser.setFileFilter(filter);
                        int returnVal = fileChooser.showOpenDialog(this);
                        if (returnVal == JFileChooser.APPROVE_OPTION) {
                                File file = fileChooser.getSelectedFile();
                                try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
                                        logArea.read(reader, null);
                                }
                                catch (IOException ex) {
                                        JOptionPane.showMessageDialog(this, "无法打开文件: " + ex.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
                                }
                        }
                });
                menu.add(openItem);
                menu.add(saveItem);
                menuBar.add(menu);
                setJMenuBar(menuBar);
                // 顶部状态面板
                JPanel statusPanel = new JPanel(new GridLayout(2, 2, 10, 5));
                lblSpaces = new JLabel("剩余车位: 20");
                lblSpaces.setFont(new Font("微软雅黑", Font.BOLD, 16));
                progressBar = new JProgressBar(0, 20);
                progressBar.setValue(20);
                progressBar.setStringPainted(true);
                lblIncome = new JLabel("总收入: 0 元");
                lblCount = new JLabel("车流量: 0 辆");
                statusPanel.add(lblSpaces);
                statusPanel.add(progressBar);
                statusPanel.add(lblIncome);
                statusPanel.add(lblCount);
                //添加按钮用于暂停模拟器
                JButton pauseButton = new JButton("暂停");
                pauseButton.addActionListener(e -> {
                        pauseLock.lock();
                        try {
                                if (isPaused) {
                                        // 恢复线程
                                        isPaused = false;
                                        pauseButton.setText("暂停");
                                        pauseCondition.signalAll();
                                } else {
                                        // 暂停线程
                                        isPaused = true;
                                        pauseButton.setText("继续");
                                }
                        } finally {
                                pauseLock.unlock();
                        }
                });
                statusPanel.add(pauseButton, BorderLayout.NORTH);
                // VIP等待列表
                vipListModel = new DefaultListModel<>();
                vipList = new JList<>(vipListModel);
                JScrollPane vipScroll = new JScrollPane(vipList);
                vipScroll.setBorder(BorderFactory.createTitledBorder("VIP等待队列"));
                // 日志区域
                logArea = new JTextArea();
                // 设置不可编辑
                logArea.setEditable(false);
                JScrollPane logScroll = new JScrollPane(logArea);
                logScroll.setBorder(BorderFactory.createTitledBorder("操作日志"));
                // 布局组合
                JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, vipScroll, logScroll);
                splitPane.setResizeWeight(0.3);
                mainPanel.add(statusPanel, BorderLayout.NORTH);
                mainPanel.add(splitPane, BorderLayout.CENTER);
                add(mainPanel);
        }
        private void startThreads() {
                ExecutorService exec = Executors.newCachedThreadPool();
                // 普通车辆生成并入库
                exec.execute(() -> generateVehicles(false));
                // VIP车辆生成并入库
                exec.execute(() -> generateVehicles(true));
                // 出口线程
                exec.execute(() -> {
                        Random rand = new Random();
                        while (true) {
                                // 检查暂停状态并等待
                                pauseLock.lock();
                                try {
                                        while (isPaused) {
                                                pauseCondition.await();
                                        }
                                } catch (InterruptedException ex) {
                                        Thread.currentThread().interrupt();
                                } finally {
                                        pauseLock.unlock();
                                }
                                // 等待1~3时间，可被暂停中断
                                long waitTime = rand.nextInt(2000) + 1000;
                                try {
                                        pauseLock.lock();
                                        if (!isPaused) {
                                                pauseCondition.await(waitTime, TimeUnit.MILLISECONDS);
                                        }
                                } catch (InterruptedException ex) {
                                        Thread.currentThread().interrupt();
                                } finally {
                                        pauseLock.unlock();
                                }
                                // 再次检查是否暂停
                                if (isPaused) {
                                        continue;
                                }
                                // 处理车辆离开
                                try {
                                        parkingLot.exit((vehicle, duration) -> {
                                                int fee = calculateFee(vehicle, 5);
                                                totalIncome.addAndGet(fee);
                                                //  车辆数加1
                                                vehicleCount.incrementAndGet();
                                                String log = String.format("[%s] %s VIP:%s 停留%d分钟 收费%d元",
                                                                LocalDateTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss")),
                                                                vehicle.id, vehicle.isVip, 5, fee);
                                                updateUI(log, fee);
                                                logQueue.put(log);
                                        });
                                } catch (InterruptedException e) {
                                        Thread.currentThread().interrupt();
                                }
                        }
                });
        }
        private void startLogWriter() {
                Executors.newSingleThreadExecutor().execute(() -> {
                        try (BufferedWriter writer = new BufferedWriter(new FileWriter("parking.log", true))) {
                                while (!Thread.currentThread().isInterrupted()) {
                                        String log = logQueue.take();
                                        writer.write(log);
                                        writer.newLine();
                                        writer.flush();
                                }
                        } catch (InterruptedException | IOException e) {
                                e.printStackTrace();
                        }
                });
        }
        private void generateVehicles(boolean isVip) {
                Random rand = new Random();
                DateTimeFormatter dtf = DateTimeFormatter.ofPattern("HHmmss");
                while (true) {
                        // 检查暂停状态并等待
                        pauseLock.lock();
                        try {
                                while (isPaused) {
                                        pauseCondition.await();
                                }
                        } catch (InterruptedException ex) {
                                Thread.currentThread().interrupt();
                        } finally {
                                pauseLock.unlock();
                        }
                        // 等待随机时间，可被暂停中断
                        long waitTime = rand.nextInt(isVip ? 3000 : 1500) + 500;
                        try {
                                pauseLock.lock();
                                if (!isPaused) {
                                        pauseCondition.await(waitTime, TimeUnit.MILLISECONDS);
                                }
                        } catch (InterruptedException ex) {
                                Thread.currentThread().interrupt();
                        } finally {
                                pauseLock.unlock();
                        }
                        // 再次检查是否暂停
                        if (isPaused) {
                                continue;
                        }
                        // 生成车辆并处理进入停车场
                        try {
                                String carId = (isVip ? "V" : "N") +
                                                LocalDateTime.now().format(dtf) +
                                                (char)(65 + rand.nextInt(26));
                                Vehicle vehicle = new Vehicle(carId, isVip);
                                //尝试进入停车场,如失败且是vip则加入vip等待队列
                                if (parkingLot.enter(vehicle)) {
                                        String log = String.format("[%s] %s %s",
                                                        LocalDateTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss")),
                                                        vehicle.id, isVip ? "VIP优先进入" : "进入");
                                        updateUI(log, 0);
                                        logQueue.put(log);
                                } else if (isVip) {
                                        SwingUtilities.invokeLater(() -> vipListModel.addElement(vehicle.id));
                                }
                        } catch (InterruptedException e) {
                                Thread.currentThread().interrupt();
                        }
                }
        }
        private int calculateFee(Vehicle vehicle, int durationMinutes) {
                int hours = (int) Math.ceil(durationMinutes / 60.0);
                return vehicle.isVip ? (hours * 3) : (5 + (hours-1)*3);
        }
        private void updateUI(String log, int fee) {
                SwingUtilities.invokeLater(() -> {
                        logArea.append(log + "\n");
                        lblSpaces.setText("剩余车位: " + parkingLot.getAvailableSpaces());
                        progressBar.setValue(parkingLot.getOccupiedSpaces());
                        lblIncome.setText("总收入: " + totalIncome + " 元");
                        lblCount.setText("车流量: " + vehicleCount + " 辆");
                        // 更新VIP队列
                        vipListModel.clear();
                        parkingLot.getVipQueue().forEach(vipListModel::addElement);
                });
        }
}
class ParkingLot {
        private final int capacity;
        private final PriorityQueue<Vehicle> vipQueue = new PriorityQueue<>((a,b) -> Boolean.compare(b.isVip, a.isVip));
        private final Queue<Vehicle> regularQueue = new LinkedList<>();
        private final ReentrantLock lock = new ReentrantLock();
        private int occupied;
        public ParkingLot(int capacity) {
                this.capacity = capacity;
        }
        public boolean enter(Vehicle vehicle) {
                lock.lock();
                try {
                        if (occupied < capacity) {
                                occupied++;
                                vehicle.enterTime = System.currentTimeMillis();
                                return true;
                        }
                        //车位已满，且为vip，加入vip队列
                        if (vehicle.isVip) {
                                vipQueue.offer(vehicle);
                                tryEvictRegularCar();
                        }
                        return false;
                } finally {
                        lock.unlock();
                }
        }
        private void tryEvictRegularCar() {
                if (!regularQueue.isEmpty()) {
                        Vehicle toRemove = regularQueue.poll();
                        occupied--;
                        vipQueue.offer(toRemove);
                }
        }
        public void exit(ExitHandler handler) throws InterruptedException {
                lock.lock();
                try {
                        if (occupied == 0) return;
                        Vehicle vehicle = !vipQueue.isEmpty() ?
                                        vipQueue.poll() : regularQueue.poll();
                        if (vehicle != null) {
                                occupied--;
                                long duration = (System.currentTimeMillis() - vehicle.enterTime) / 60000;
                                handler.handleExit(vehicle, (int)duration);
                        }
                        // 优先处理VIP队列
                        while (!vipQueue.isEmpty() && occupied < capacity) {
                                Vehicle vip = vipQueue.poll();
                                occupied++;
                                regularQueue.offer(vip);
                        }
                } finally {
                        lock.unlock();
                }
        }
        public int getAvailableSpaces() {
                return capacity - occupied;
        }
        public int getOccupiedSpaces() {
                return occupied;
        }
        //  获取VIP车牌链表
        public Queue<String> getVipQueue() {
                lock.lock();
                try {
                        Queue<String> ids = new LinkedList<>();
                        vipQueue.forEach(v -> ids.add(v.id));
                        return ids;
                } finally {
                        lock.unlock();
                }
        }
        //车辆离开接口
        interface ExitHandler {
                void handleExit(Vehicle vehicle, int durationMinutes) throws InterruptedException;
        }
}
class Vehicle {
        String id;
        boolean isVip;
        long enterTime;
        public Vehicle(String id, boolean isVip) {
                this.id = id;
                this.isVip = isVip;
        }
}